import {_decorator, BoxCollider, Component, ITriggerEvent, lerp, math, Node, ParticleSystem, Vec3} from 'cc';
import {ColliderGroupEnum} from "db://assets/scripts/game/ColliderGroupEnum";
import {GameManager} from "db://assets/scripts/game/GameManager";
import {ResourceUtils} from "db://assets/scripts/common/ResourceUtils";
import {PoolManager} from "db://assets/scripts/common/PoolManager";
import {MonsterController} from "db://assets/scripts/game/role/monster/MonsterController";
import {GameState} from "db://assets/scripts/game/GameState";

const {ccclass, property} = _decorator;

/**
 * 弓箭控制器
 */
@ccclass('ArrowController')
export class ArrowController extends Component {
    /**
     * 箭是否自动调整角度
     */
    public isAutoRotate: boolean = true;
    /**
     * 箭是否弹射
     */
    public isArrowLaunch: boolean = false;

    /**
     * 放弓箭特效的节点
     */
    private bodyNode: Node;
    /**
     * 当前速度
     */
    private currentSpeed: number = 0;
    /**
     * 目标速度
     */
    private targetSpeed: number = 0;
    /**
     * 初始默认位置
     */
    private originPosition: Vec3;
    /**
     * 初始默认角度
     */
    private originEulerAngles: Vec3 = null!
    /**
     * 和玩家之间的向量差
     */
    private offsetPosition: Vec3 = new Vec3();
    /**
     * 当前节点世界坐标
     */
    private currentWorldPosition: Vec3 = new Vec3();
    /**
     * 箭节点超过玩家这个范围则隐藏
     */
    private disappearRange: number = 25;
    /**
     * 是否已经加载完所有特效
     */
    private isLoadEffectOver: boolean = false;
    /**
     * 是否需要特效
     */
    private isNeedShowEffect: boolean = false;
    /**
     * 箭的下次目标位置
     */
    private targetWorldPosition: Vec3 = new Vec3();
    /**
     * 当前角度
     */
    private currentEulerAngles: Vec3 = new Vec3();
    /**
     * 初始朝向
     */
    private originForward: Vec3;
    /**
     * 当前朝向
     */
    private currentForward: Vec3 = new Vec3();
    /**
     * 技能释放位置的世界坐标
     */
    private releaseWorldPosition: Vec3 = new Vec3();
    /**
     * 向量差
     */
    private offsetPosition1: Vec3 = new Vec3();
    /**
     * 向量差
     */
    private offsetPosition2: Vec3 = new Vec3();
    /**
     * 两个向量叉乘
     */
    private cross: Vec3 = new Vec3();
    /**
     * 碰撞体
     */
    private comCollider: BoxCollider;

    onLoad() {
        this.comCollider = this.node.getComponent(BoxCollider);
    }

    onEnable() {
        this.comCollider.on('onTriggerEnter', this.onTriggerEnterCb, this);
    }

    onDisable() {
        this.comCollider.off('onTriggerEnter', this.onTriggerEnterCb, this);
    }

    start() {

    }

    update(deltaTime: number) {
        if (!this.node.parent
            || !GameManager.getInstance().gamePlayerProxy.getPlayerNode()
            || GameManager.getInstance().gameStateProxy.getGameState() === GameState.OVER
            || GameManager.getInstance().gameStateProxy.getGameState() === GameState.PAUSE
            || (this.isNeedShowEffect && !this.isLoadEffectOver)) {
            return;
        }

        //朝forward方向飞行
        this.currentSpeed = lerp(this.targetSpeed, this.currentSpeed, 0.25);
        this.targetWorldPosition.set(0, 0, -deltaTime * this.currentSpeed);
        this.node.translate(this.targetWorldPosition, Node.NodeSpace.LOCAL);
        this.currentWorldPosition.set(this.node.worldPosition);

        //超过玩家一定范围则隐藏
        Vec3.subtract(this.offsetPosition, this.currentWorldPosition, GameManager.getInstance().gamePlayerProxy.getPlayerNode().worldPosition);
        if (this.offsetPosition && this.offsetPosition.length() >= this.disappearRange) {
            this.hideArrow();
        }
    }

    /**
     * 初始化
     *
     * @param speed 速度
     * @param releaseWorldPosition 技能释放位置
     * @param isPreload 是否预加载
     */
    public init(speed: number, releaseWorldPosition: Vec3, isPreload: boolean = false) {
        this.releaseWorldPosition.set(releaseWorldPosition);

        if (!this.bodyNode) {
            this.bodyNode = this.node.getChildByName("body");
        }

        this.isLoadEffectOver = false;
        this.isNeedShowEffect = false;
        this.disappearRange = isPreload ? 5 : 25;

        this.isArrowLaunch = false;

        if (!this.originPosition) {
            this.originPosition = this.node.position.clone();
        }

        if (!this.originEulerAngles) {
            this.originEulerAngles = this.node.eulerAngles.clone();
        }

        if (!this.originForward) {
            this.originForward = this.node.forward.clone();
        }

        this.node.active = false;
        this.node.setPosition(this.originPosition);
        this.node.eulerAngles = this.originEulerAngles;
        this.currentForward.set(this.originForward);

        this.targetSpeed = speed;
        this.currentSpeed = speed * 0.5;

        this.bodyNode.children.forEach((ndChild: Node) => {
            if (ndChild.name.startsWith("arrow")) {
                ndChild.active = false;
            }
        })

        let isHasIce = GameManager.getInstance().gamePlayerProxy.getPlayerController().isArrowIce;
        let isHasFire = GameManager.getInstance().gamePlayerProxy.getPlayerController().isArrowFire;
        let isHasLightning = GameManager.getInstance().gamePlayerProxy.getPlayerController().isArrowLightning;

        //根据玩家拥有的不同技能展示对应特效
        if (isHasFire || isHasIce || isHasLightning) {
            this.isNeedShowEffect = true;

            if (isHasFire && isHasIce && isHasLightning) {
                this.showTrail("arrowAll");
            } else {
                if ((isHasFire && isHasIce) || (isHasFire && isHasLightning) || (isHasIce && isHasLightning)) {
                    if (isHasFire && isHasIce) {
                        this.showTrail("arrowFireIce");
                    } else if (isHasLightning && isHasFire) {
                        this.showTrail("arrowLightningFire");
                    } else if (isHasLightning && isHasIce) {
                        this.showTrail("arrowLightningIce");
                    }
                } else {
                    if (isHasFire) {
                        this.showTrail("arrowFire");
                    } else if (isHasIce) {
                        this.showTrail("arrowIce");
                    } else if (isHasLightning) {
                        this.showTrail("arrowLightning");
                    }
                }
            }
        } else {
            //不展示特效
            this.bodyNode.children.forEach((ndChild: Node) => {
                if (ndChild.name.startsWith("arrow")) {
                    ndChild.active = false;
                }
            })

            this.node.active = true;
        }
    }

    /**
     * 展示箭的特效拖尾
     *
     * @param {string} effectName
     * @memberof Arrow
     */
    private showTrail(effectName: string) {
        let ndTrail: Node | null = this.bodyNode.getChildByName(effectName);
        if (ndTrail) {
            ndTrail.active = true;
            this.node.active = true;
            this.isLoadEffectOver = true;
        } else {
            ResourceUtils.loadEffect(`arrow/${effectName}`).then((pf: any) => {
                ndTrail = PoolManager.getInstance().getNode(pf, this.bodyNode);
                this.node.active = true;
                this.isLoadEffectOver = true;
            });
        }
    }

    /**
     *  回收弓箭组，在weapon/arrow下
     *
     * @memberof Arrow
     */
    public recycleArrowGroup() {
        if (this.node.parent) {
            PoolManager.getInstance().putNode(this.node.parent);
        }
    }

    /**
     * 击中目标,隐藏箭
     *
     * @memberof Arrow
     */
    public hideArrow() {
        if (!this.node.parent) {
            return;
        }

        //清除拖尾特效残留
        let arrParticle: ParticleSystem[] = this.bodyNode.getComponentsInChildren(ParticleSystem);
        arrParticle.forEach((item: ParticleSystem) => {
            item.simulationSpeed = 1;
            item?.clear();
            item?.stop();
        })

        this.node.active = false;

        //如果弓箭组里所有的箭都隐藏了则回收整个弓箭组
        let isAllArrowHide = this.node.parent?.children.every((ndArrow: Node) => {
            return ndArrow.active === false;
        })

        if (isAllArrowHide) {
            this.recycleArrowGroup();
        }
    }

    /**
     * 箭弹射给一定范围内的某个敌人
     *
     * @param {Node} ndMonster
     * @memberof Arrow
     */
    public playArrowLaunch(ndMonster: Node) {
        this.isArrowLaunch = true;

        let arrTargets = GameManager.getInstance().gameGetMonsterProxy.getNearbyMonster(ndMonster);

        if (arrTargets.length) {
            let ndTarget = arrTargets[0];
            this.offsetPosition1.set(this.releaseWorldPosition.x - this.node.worldPosition.x, 0, this.releaseWorldPosition.z - this.node.worldPosition.z);
            this.offsetPosition2.set(this.node.worldPosition.x - ndTarget.worldPosition.x, 0, this.node.worldPosition.z - ndTarget.worldPosition.z);
            //两个向量之间弧度
            let radian = Vec3.angle(this.offsetPosition1, this.offsetPosition2);
            //角度
            let angle = math.toDegree(radian);
            //叉乘
            Vec3.cross(this.cross, this.offsetPosition1, this.offsetPosition2);
            //判断正反角度
            if (this.cross.y > 0) {
                this.currentEulerAngles.y = angle;
            } else {
                this.currentEulerAngles.y = -angle;
            }

            this.node.eulerAngles = this.currentEulerAngles;
        }
    }

    private onTriggerEnterCb(event: ITriggerEvent) {
        // this._hitTarget(event.otherCollider, event.selfCollider);
        if (GameManager.getInstance().gameStateProxy.getGameState() === GameState.OVER
            || GameManager.getInstance().gameStateProxy.getGameState() !== GameState.PLAYING) {
            return;
        }

        let otherCollider = event.otherCollider;

        if (otherCollider.getGroup() === ColliderGroupEnum.OBSTACLE) {
            //箭碰到游戏中的障碍则回收
            let scriptArrow = this.node.getComponent(ArrowController);
            scriptArrow.hideArrow();

        } else if (otherCollider.getGroup() === ColliderGroupEnum.MONSTER) {
            //箭碰到敌人
            let ndMonster = otherCollider.node;
            let monsterController = ndMonster.getComponent(MonsterController);
            let arrowController = this.node.getComponent(ArrowController);

            //箭是否弹射
            if (GameManager.getInstance().gamePlayerProxy.getPlayerController().isArrowLaunch) {
                if (!arrowController.isArrowLaunch) {
                    //第一次弹射
                    arrowController.playArrowLaunch(ndMonster);
                } else {
                    //第二次直接隐藏
                    arrowController.hideArrow();
                }
            } else if (GameManager.getInstance().gamePlayerProxy.getPlayerController().isArrowPenetrate) {
                //箭穿透
            } else {
                arrowController.hideArrow();
            }

            monsterController.playHit(arrowController.isArrowLaunch);

            //龙被射到龙改变颜色
            if (ndMonster.name === "dragon") {
                //@ts-ignore

                monsterController.changeDragonMat();
            }
        }
    }
}

